package test.ground.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.wang.tool.monitor.InvokeTemplate;
import com.wang.tool.monitor.template.AbsMonitorInvoker;
import com.wang.tool.trace.TraceContext;
import com.wang.tool.trace.TraceHolder;
import com.wang.tool.util.CommonUtil;
import com.wang.tool.util.SimpleLogUtil;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

public class WebTraceMonitorFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        String traceId = httpRequest.getHeader(TraceHolder.TRACE_ID_HEADER);
        String rpcId = httpRequest.getHeader(TraceHolder.RPC_ID_HEADER);
        String payloadStr = httpRequest.getHeader(TraceHolder.ATTRIBUTES_HEADER);
        Map<String, Object> attributes = null;
        if (payloadStr != null) {
            try {
                attributes = JSON.parseObject(payloadStr, new TypeReference<Map<String, Object>>() {
                });
            } catch (Throwable e) {
                SimpleLogUtil.error("trace_attr_parse_error", e);
            }
        }
        TraceContext traceContext = null;
        if (CommonUtil.isBlank(traceId)) {
            traceContext = TraceContext.newTrace();
        } else {
            traceContext = TraceContext.build(traceId, rpcId, attributes);
        }
        if (traceContext == null) {
            // 继续处理请求
//            httpRequest.getScheme()
            InvokeTemplate.monitor("web_in", httpRequest.getScheme()+"_"+httpRequest.getMethod(), httpRequest.getRequestURI(), new AbsMonitorInvoker<Void>(httpRequest.getParameterMap()) {
                @Override
                public Void internalCall() throws Throwable {
                    // 继续处理请求
                    chain.doFilter(request, response);
                    return null;
                }
            });
            return;
        }
        //将trace设置到线程中
        try {
            TraceHolder.set(traceContext);

            // 在响应中添加Trace ID和Span ID
            httpResponse.setHeader(TraceHolder.TRACE_ID_HEADER, traceContext.getTraceId());
            httpResponse.setHeader(TraceHolder.RPC_ID_HEADER, traceContext.getRpcId());
            if (traceContext.getAttributes() != null) {
                httpResponse.setHeader(TraceHolder.ATTRIBUTES_HEADER, JSON.toJSONString(traceContext.getAttributes()));
            }

            InvokeTemplate.monitor("web_in", httpRequest.getScheme()+"_"+httpRequest.getMethod(), httpRequest.getRequestURI(), new AbsMonitorInvoker<Void>(httpRequest.getParameterMap()) {
                @Override
                public Void internalCall() throws Throwable {
                    // 继续处理请求
                    chain.doFilter(request, response);
                    return null;
                }
            });
        } finally {
            TraceHolder.clear();
        }
    }

    @Override
    public void destroy() {
    }
}